package com.xiaolei.fastnio.library

import com.xiaolei.fastnio.library.Workers.ClientAcceptWorker
import com.xiaolei.fastnio.library.Workers.SelectorQueueWorker
import com.xiaolei.fastnio.library.Adapters.Impls.EchoClientAdapter
import com.xiaolei.fastnio.library.Executors.ExecutorServices
import com.xiaolei.fastnio.library.Factorys.IClientAdapterFactory
import com.xiaolei.fastnio.library.Factorys.Impls.CacheClientAdapterFactory
import com.xiaolei.fastnio.library.Workers.ClientReadWorker
import java.net.InetSocketAddress
import java.nio.channels.SelectionKey
import java.nio.channels.Selector
import java.nio.channels.ServerSocketChannel
import java.util.concurrent.*

object NioServer : AutoCloseable
{
    private var serverChannel: ServerSocketChannel? = null

    // 主机名
    private var host: String = "0.0.0.0"

    // 端口
    private var port: Int? = null

    // 客户端进入适配器
    private var acceptSelector: Selector? = null

    // 数据读取适配器
    private var readSelector: Selector? = null

    // 核心线程池，监听 【ACCEPT，READ】 2个
    private var coreService: ExecutorService? = null

    /**
     * --读取数据--配置开始--------
     */
    // 读取数据线程池
    private var readerService: ExecutorService? = null

    // 读取数据的线程数
    private var readWorkerCount = Runtime.getRuntime().availableProcessors() * 3

    // 同时处理的读数据请求数排队
    private var readWorkerCapacity = 1024

    // 每次循环读取数据的缓冲大小
    private var readBufferSize = 1024

    /**
     * --读取数据--配置结束--------
     */

    // 生产客户端Adapter的工厂类
    private var clientFactory: IClientAdapterFactory<*> = CacheClientAdapterFactory(
            EchoClientAdapter::class)

    /**
     * 设置主机名称
     */
    fun host(host: String): NioServer
    {
        NioServer.host = host
        return this
    }

    /**
     * 设置监听端口号
     */
    fun setPort(port: Int): NioServer
    {
        NioServer.port = port
        return this
    }

    /**
     * 设置客户端的处理类
     */
    fun setClientAdapterFactory(factory: IClientAdapterFactory<*>): NioServer
    {
        clientFactory = factory
        return this
    }

    /**
     * 设置读取服务的线程数
     */
    fun setMaxReadWorker(workerCount: Int): NioServer
    {
        readWorkerCount = workerCount
        return this
    }

    /**
     * 设置同时可接受处理的数据读取请求数，默认1024
     */
    fun setReadWorkerCapacity(capacity: Int): NioServer
    {
        readWorkerCapacity = capacity
        return this
    }

    /**
     * 设置读取的缓冲区大小，
     * 每个ReadWorker都会有一个这么大小的对应的buffer
     */
    fun setReadBufferSize(bufferSize: Int): NioServer
    {
        readBufferSize = bufferSize
        return this
    }

    /**
     * 启动NIO服务
     */
    fun start()
    {
        if (serverChannel != null)
        {
            throw IllegalStateException("已存在")
        }
        if (port == null)
        {
            throw IllegalStateException("端口号")
        }
        synchronized(NioServer) {
            if (serverChannel == null)
            {
                synchronized(NioServer) {
                    acceptSelector = Selector.open()
                    readSelector = Selector.open()
                    serverChannel = ServerSocketChannel.open()

                    coreService = ExecutorServices.newFixedThreadPool(2, groupName = "CoreService")
                    readerService = ExecutorServices.newFixedThreadPool(readWorkerCount, groupName = "ReadWorker")

                    startDelegate(
                            serverChannel = serverChannel!!,
                            acceptSelector = acceptSelector!!,
                            readSelector = readSelector!!,
                            port = port!!,
                            clientFactory = clientFactory,
                            coreService = coreService!!,
                            readerService = readerService!!
                    )
                }
            }
        }
    }

    /**
     * 代理启动
     */
    private inline fun startDelegate(serverChannel: ServerSocketChannel,
                                     acceptSelector: Selector,
                                     readSelector: Selector,
                                     port: Int,
                                     clientFactory: IClientAdapterFactory<*>,
                                     coreService: ExecutorService,
                                     readerService: ExecutorService)
    {
        try
        {
            serverChannel.bind(InetSocketAddress(host, port))
            // 非阻塞
            serverChannel.configureBlocking(false)
            // 监听就绪事件
            serverChannel.register(acceptSelector, SelectionKey.OP_ACCEPT)

            // 可读取队列
            val readQueue = LinkedBlockingQueue<SelectionKey>(readWorkerCapacity)
            // 实力化核心代理器
            val clientAcceptWorker = ClientAcceptWorker(acceptSelector, readSelector, clientFactory)
            val clientReadAcceptWorker = SelectorQueueWorker(readSelector, readQueue)

            // 启动核心服务
            coreService.submit(clientAcceptWorker)
            coreService.submit(clientReadAcceptWorker)
            // 启动读取服务
            for (i in 0 until readWorkerCount)
            {
                readerService.submit(ClientReadWorker(readQueue, readSelector, clientFactory, readBufferSize))
            }
            println("服务器已启动")
        } catch (e: Exception)
        {
            close()
        }
    }

    /**
     * 关闭服务器
     */
    override fun close()
    {
        try
        {
            // 关闭核心线程池
            coreService?.shutdown()

            // 关闭读取线程池
            readerService?.shutdown()

            // 服务器的通道
            serverChannel?.close()

            // 连接的选择器
            acceptSelector?.close()

            // 读取的选择器
            readSelector?.close()

        } catch (e: Exception)
        {
            e.printStackTrace()
        } finally
        {
            coreService = null
            readerService = null
            serverChannel = null
            acceptSelector = null
            readSelector = null
        }
    }
}